package client_core

import (
	"context"
	"github.com/chicken-team-outside/chicken_transmission/api_messages"
	"github.com/chicken-team-outside/chicken_transmission/client_core/config"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"sync/atomic"
)

var coreInitCtx atomic.Value

func initFsApi(group *gin.RouterGroup) {
	group.GET("/rpc_config", getRpcConfig)
	group.POST("/rpc_config", setRpcConfig)
	group.POST("/change_connect", changeRpcConnect)
	initFsOpApi(group.Group("/op"))
	initCtx, initDone := context.WithCancel(context.Background())
	coreInitCtx.Store(initCtx)
	go func() {
		defer initDone()
		initCore()
	}()
}

func initCore() {
	initSfsClient()
	if config.LocalDiskEnabled() {
		if err := tryLoadAndSetLocalDriver(); err != nil {
			zap.L().Warn("failed to create local driver", zap.Error(err))
			if err = config.SaveLocalDiskEnabled(false); err != nil {
				zap.L().Error("failed to save disabled local driver", zap.Error(err))
			}
		}
	}
	if config.NetDiskEnabled() {
		if err := tryLoadAndSetNetDiskToSfsClient(); err != nil {
			zap.L().Warn("failed to create net disk driver", zap.Error(err))
			if err = config.SaveNetDiskEnabled(false); err != nil {
				zap.L().Error("failed to save disabled net disk driver", zap.Error(err))
			}
		}
	}
}

type ServiceStatus int

const (
	ServiceStatusSuccess ServiceStatus = iota
	ServiceStatusFailure
	ServiceStatusDisabled
	ServiceStatusConnecting
	ServiceStatusClosing
)

type ServiceStatusInfo struct {
	Local      ServiceStatus                    `json:"local"`
	NetDisk    ServiceStatus                    `json:"net_disk"`
	Rpc        ServiceStatus                    `json:"rpc"`
	ClientList []*api_messages.ClientStatusInfo `json:"client_list"`
}

func getRpcStatus() ServiceStatus {
	if sfsClient.IsConnected() {
		return ServiceStatusSuccess
	} else {
		return ServiceStatusFailure
	}
}

func getCurrentStatus(ctx context.Context) (info *ServiceStatusInfo) {
	select {
	case <-ctx.Done():
		return nil
	case <-coreInitCtx.Load().(context.Context).Done():
	}
	info = &ServiceStatusInfo{}
	if config.NetDiskEnabled() {
		if sfsClient.GetNetDisk() == nil {
			info.NetDisk = ServiceStatusFailure
		} else {
			info.NetDisk = ServiceStatusSuccess
		}
	} else {
		info.NetDisk = ServiceStatusDisabled
	}
	if config.LocalDiskEnabled() {
		if sfsClient.GetLocal() == nil {
			info.Local = ServiceStatusFailure
		} else {
			info.Local = ServiceStatusSuccess
		}
	} else {
		info.Local = ServiceStatusDisabled
	}
	info.Rpc = getRpcStatus()
	info.ClientList = sfsClient.GetClients()
	return
}

func getRpcConfig(ctx *gin.Context) {
	Success(ctx, config.RpcServerConfig(), "成功")
}

func setRpcConfig(ctx *gin.Context) {
	cfg := &config.RpcServerSetting{}
	err := ctx.BindJSON(cfg)
	if err != nil {
		BadRequest(ctx, "参数错误")
		return
	}
	err = connectRpcServerByConfig(ctx, cfg)
	if err != nil {
		BadRequest(ctx, "连接服务失败: "+err.Error())
		return
	}
	err = config.SaveRpcServerSetting(cfg)
	if err != nil {
		BadRequest(ctx, "保存配置失败: "+err.Error())
	} else {
		Success(ctx, nil, "成功")
	}
}

func changeRpcConnect(ctx *gin.Context) {
	var connect bool
	err := ctx.BindJSON(&connect)
	if err != nil {
		BadRequest(ctx, "参数错误")
		return
	}
	if connect {
		if !sfsClient.IsConnected() {
			err = connectRpcServer(ctx)
			if err != nil {
				BadRequest(ctx, "连接服务器失败: "+err.Error())
				return
			}
		}
	} else {
		sendRpcStatusChange(ServiceStatusClosing)
		sfsClient.Disconnect()
	}
	Success(ctx, nil, "成功")
}
